interface TreeHelperConfig {
  id: string
  children: string
  pid: string
  empty_children?: boolean
}

const DEFAULT_CONFIG: TreeHelperConfig = {
  id: "id",
  children: "children",
  pid: "parentId",
  empty_children: false // 是否移除无用空children
}

const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config)

export function listToTree<T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] {
  const conf = getConfig(config) as TreeHelperConfig
  const nodeMap = new Map()
  const result: T[] = []

  const { id, children, pid } = conf
  // 为每一个元素添加children字段，
  for (const node of list) {
    node[children] = node[children] || []
    nodeMap.set(node[id], node)
  }

  for (const node of list) {
    const parent = nodeMap.get(node[pid])
    const p = parent ? parent.children : result
    p.push(node)
  }

  if (!conf.empty_children) {
    removeEmptyChildren(result, conf)
  }
  return result
}

export function treeToList<T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T {
  config = getConfig(config)
  const { children } = config
  const result: any = [...tree]
  for (let i = 0; i < result.length; i++) {
    if (!result[i][children!]) continue
    result.splice(i + 1, 0, ...result[i][children!])
  }
  return result
}

function removeEmptyChildren(tree: any, config: Partial<TreeHelperConfig> = {}) {
  const conf = getConfig(config)
  const { children } = conf
  tree.forEach((element: any) => {
    if (element[children!] && element[children!].length) {
      removeEmptyChildren(element[children!], conf)
    } else {
      delete element[children!]
    }
  })
  return tree
}
